﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace frag_boardgame
{
    /// <summary>
    /// This class will handle the player module
    /// </summary>
    [DataContract]
    public class Player : IBounds
    {

        public enum Controller { AI, Human };

        [DataMember]
        private Controller control;


        public Controller Control
        {
            get { return control; }
            set { control = value; }
        }

        [DataMember]
        private int _MovesLeft;

        [DataMember]
        private int _ShotsLeft;

        [DataMember]
        private int health;

        [DataMember]
        private int speed;

        [DataMember]
        private int accuracy;

        [DataMember]
        private int id;

        private static int NumOfPlayers = 0;

        [DataMember]
        private int row;

        [DataMember]
        private int col;

        [DataMember]
        PlayerConfiguration config;

        public int Health
        {
            get { return health; }
            set
            {
                health = value;
                if (health < 0)
                {
                    health = 0;
                }
                if (health > config.MaxHealth)
                {
                    health = config.MaxHealth;
                }
            }
        }

        public int Speed {
            get { return speed; }
            set { speed = value; }
        }


        public int Accuracy
        {
            get { return accuracy; }
            set { accuracy = value; }
        }

        public int MaxHealth
        {
            get { return config.MaxHealth; }
        }

        public static int PlayersCount
        {
            set { NumOfPlayers = value; }
        }


        public Player(PlayerConfiguration config, int ID)
        {
            this.control = config.Control;
            this.config = config;
            Health = config.MaxHealth;
            accuracy = config.StartingAccuracy;
            speed = config.StartingSpeed;
            NumOfPlayers++;
            id = ID;
            this.row = config.StartingPosition.row;
            this.col = config.StartingPosition.col;
        }

        public String Name
        {
            get { return config.Name; }
        }

        public int Row
        {
            get
            {
                return row;

            }
            set
            {
                row = value;
            }
        }

        public int Column
        {
            get
            {
                return col;
            }
            set
            {
                col = value;
            }
        }

        public Square Square
        {
            set
            {
                row = value.Row;
                col = value.Column;
            }
        }

        public int ID
        {
            get { return id; }
        }

        public int MovesLeft
        {
            get
            {
                return _MovesLeft;
            }
            set
            {
                _MovesLeft = value;
            }
        }


        public int ShotsLeft
        {
            get { return _ShotsLeft; }
            set { _ShotsLeft = value; }
        }

        public override string ToString()
        {
            return Name;
        }

        public void getHit(int damage)
        {
            Health = Health - damage;
        }

        // override object.Equals
        public override bool Equals(object obj)
        {
            Player p = obj as Player;
            if (p == null) return false;

            return Equals(p._MovesLeft,_MovesLeft) &&
                Equals(p._ShotsLeft, _ShotsLeft) &&
                Equals(p.config, config) &&
                Equals(p.health, health) &&
                Equals(p.Row, Row) &&
                Equals(p.Column, Column);
        }

        // override object.GetHashCode
        public override int GetHashCode()
        {
            return _MovesLeft.GetHashCode() ^ _ShotsLeft.GetHashCode() ^ health.GetHashCode() ^
                config.GetHashCode() ^ Row.GetHashCode() ^ Column.GetHashCode();
        }

        public bool isDead()
        {
            if (Health == 0)
            {
                return true;
            }
            return false;
        }

        public float calculateDistance(Player player,GameData gameData)
        {
            Square sqr = gameData.Board.GetSquare(Row, Column);
            return sqr.calculateDistance(gameData.Board.GetSquare(player.Row, player.Column));
        }

        public float calculateHorizontalDistance(Player player, GameData gameData)
        {
            Square sqr = gameData.Board.GetSquare(Row, Column);
            return sqr.calculateHorizontalDistance(gameData.Board.GetSquare(player.Row, player.Column));
        }

        public float calculateVerticalDistance(Player player, GameData gameData)
        {
            Square sqr = gameData.Board.GetSquare(Row, Column);
            return sqr.calculateVerticalDistance(gameData.Board.GetSquare(player.Row, player.Column));
        }


        #region IBounds Members

        public bool IsCrossing(Line line)
        {
            foreach (Line bound in GetBound())
            {
                if (Line.AreCrossing(bound,line))
                    return true;
            }
            return false;
          
        }

        public ICollection<Line> GetBound()
        {
            List<Line> lines = new List<Line>();
            lines.Add(new Line(Column +0.1, Row + 0.1, Column + 0.9, Row + 0.1));
            lines.Add(new Line(Column + 0.1, Row + 0.9, Column + 0.9, Row + 0.9));
            lines.Add(new Line(Column + 0.1, Row + 0.1, Column + 0.1, Row + 0.9));
            lines.Add(new Line(Column + 0.9, Row + 0.1, Column + 0.9, Row + 0.9));
            return lines;
        }

        #endregion
    }
}
